--[[
TODO:

]]--

--------------------------------------------------------------------------------
-- Module Declaration
--

local mod, CL = BigWigs:NewBoss("Siegecrafter Blackfuse", 953, 865)
if not mod then return end
mod:RegisterEnableMob(71504)

--------------------------------------------------------------------------------
-- Locals
--

local overloadCounter = 1
local assemblyLineCounter = 1
local shredder = EJ_GetSectionInfo(8199)
local shredderCounter = 1
local overloadCounter = 1
local sawbladeTarget

--------------------------------------------------------------------------------
-- Localization
--

local L = mod:NewLocale("enUS", true)
if L then
	L.saw_blade_near_you = "Saw blade near you (not on you)"
	L.saw_blade_near_you_desc = "You might want to turn this off to avoid spam if your raid is mostly bunched up according to your tactics."
	L.saw_blade_near_you_icon = 143265

	L.disabled = "Disabled"

	L.shredder_engage_trigger = "An Automated Shredder draws near!"
	L.laser_on_you = "Laser on you PEW PEW!"
	L.laser_say = "Laser PEW PEW"

	L.assembly_line_trigger = "Unfinished weapons begin to roll out on the assembly line."
	L.assembly_line_message = "Unfinished weapons (%d)"

	L.shockwave_missile_trigger = "Presenting... the beautiful new ST-03 Shockwave missile turret!"

	L.overcharged = "Overcharged: |cffa4c2f4%s|r"
	L.laser = "Laser"
	L.missile = "Missile"
	L.mine = "Mine"
	L.magnet = "Magnet"
end
L = mod:GetLocale()

local assemblyLineNormal, assemblyLineHeroic, overchargedHeroic

do
	local red = "ffff0000"
	local blue = "ffa4c2f4"

	assemblyLineNormal = {
		("|c%4$s%1$s|r, %2$s, %3$s"):format(L.missile, L.mine, L.laser, red),
		("%1$s, %2$s, |c%4$s%3$s|r"):format(L.mine, L.laser, L.missile, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.laser, L.magnet, L.missile, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.laser, L.missile, L.mine, red),
		("|c%4$s%1$s|r, %2$s, %3$s"):format(L.missile, L.magnet, L.mine, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.missile, L.mine, L.mine, red),
		("%1$s, %2$s, |c%4$s%3$s|r"):format(L.mine, L.laser, L.missile, red),
		("|c%4$s%1$s|r, %2$s, %3$s"):format(L.missile, L.magnet, L.mine, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.laser, L.magnet, L.laser, red),
		("|c%4$s%1$s|r, %2$s, %3$s"):format(L.missile, L.laser, L.mine, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.missile, L.magnet, L.missile, red),
		("%1$s, |c%4$s%2$s|r, %3$s"):format(L.mine, L.magnet, L.laser, red),
	}

	assemblyLineHeroic = {
		("|c%4$s%1$s|r, |c%5$s%2$s|r, %3$s"):format(L.missile, L.mine, L.laser, red, blue), -- 1
		("|c%4$s%1$s|r, %2$s, |c%5$s%3$s|r"):format(L.mine, L.laser, L.missile, red, blue), -- 2
		("%1$s, |c%5$s%2$s|r, |c%4$s%3$s|r"):format(L.laser, L.magnet, L.missile, red, blue), -- 3
		("|c%5$s%1$s|r, %2$s, |c%4$s%3$s|r"):format(L.laser, L.missile, L.mine, red, blue), -- 4
		("%1$s, |c%4$s%2$s|r, |c%5$s%3$s|r"):format(L.missile, L.magnet, L.mine, red, blue), -- 5
		("|c%4$s%1$s|r, %2$s, |c%5$s%3$s|r"):format(L.laser, L.mine, L.mine, red, blue), -- 6
		("|c%4$s%1$s|r, %2$s, |c%5$s%3$s|r"):format(L.mine, L.laser, L.missile, red, blue), -- 7
		("%1$s, |c%5$s%2$s|r, |c%4$s%3$s|r"):format(L.missile, L.magnet, L.mine, red, blue), -- 8
		("|c%4$s%1$s|r, %2$s, |c%5$s%3$s|r"):format(L.laser, L.mine, L.laser, red, blue), -- 9
		("|c%5$s%1$s|r, %2$s, |c%4$s%3$s|r"):format(L.missile, L.laser, L.mine, red, blue), -- 10
		("|c%4$s%1$s|r, |c%5$s%2$s|r, %3$s"):format(L.missile, L.magnet, L.missile, red, blue), -- 11
		("|c%4$s%1$s|r, |c%5$s%2$s|r, %3$s"):format(L.mine, L.magnet, L.laser, red, blue), -- 12
	}

	-- _G["assemblyLineHeroicDebug"] = assemblyLineHeroic
	-- /run for i = 1, 12 do print(i, assemblyLineHeroicDebug[i]) end

	overchargedHeroic = {
		L.overcharged:format(L.mine), -- 1
		L.overcharged:format(L.missile), -- 2
		L.overcharged:format(L.magnet), -- 3
		L.overcharged:format(L.laser), -- 4
		L.overcharged:format(L.mine), -- 5
		L.overcharged:format(L.mine), -- 6
		L.overcharged:format(L.missile), -- 7
		L.overcharged:format(L.magnet), -- 8
		L.overcharged:format(L.laser), -- 9
		L.overcharged:format(L.missile), -- 10
		L.overcharged:format(L.magnet), -- 11
		L.overcharged:format(L.magnet), -- 12
	}

	-- _G["overchargedHeroicDebug"] = overchargedHeroic
	-- /run for i = 1, 12 do print(i, overchargedHeroicDebug[i]) end
end

--------------------------------------------------------------------------------
-- Initialization
--

function mod:GetOptions()
	return {
		-8408,
		"saw_blade_near_you",
		{-8195, "FLASH", "SAY", "ICON"}, {145365, "TANK_HEALER"}, {143385, "TANK"}, 145774, -- Siegecrafter Blackfuse
		-8199, 144208, { 145444, "HEALER" }, -- Automated Shredders
		-8202, -8207, 143639, {-8208, "FLASH", "SAY"}, 143856, 144466, {-8212, "FLASH"},
		"berserk", "bosskill",
	}, {
		["custom_off_mine_marker"] = L.custom_off_mine_marker,
		[-8408] = "heroic",
		[-8195] = -8194, -- Siegecrafter Blackfuse
		[-8199] = -8199, -- Automated Shredders
		[-8202] = -8202, -- The Assembly Line
		["berserk"] = "general",
	}
end

function mod:OnBossEnable()
	self:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT", "CheckBossStatus")

	-- The Assembly Line
	self:Emote("AssemblyLine", L["assembly_line_trigger"])
	self:Log("SPELL_AURA_APPLIED", "CrawlerMine", 145269)
	self:Log("SPELL_AURA_APPLIED", "MagneticCrush", 144466)
	self:Log("SPELL_AURA_APPLIED", "Superheated", 143856)
	self:Log("SPELL_AURA_APPLIED_DOSE", "Superheated", 143856)
	self:RegisterEvent("RAID_BOSS_WHISPER")
	self:Yell("ShockwaveMissile", L["shockwave_missile_trigger"])
	self:Log("SPELL_AURA_APPLIED", "ShockwaveMissileOver", 143639)
	self:Log("SPELL_AURA_APPLIED", "PatternRecognitionApplied", 144236)
	self:Log("SPELL_AURA_REMOVED", "PatternRecognitionRemoved", 144236)
	-- Automated Shredders
	self:Emote("ShredderEngage", L["shredder_engage_trigger"])
	self:Log("SPELL_CAST_START", "DeathFromAbove", 144208)
	self:Log("SPELL_CAST_START", "DeathFromAboveApplied", 144210)
	self:Log("SPELL_CAST_SUCCESS", "Overload", 145444)
	-- Siegecrafter Blackfuse
	self:Log("SPELL_AURA_APPLIED_DOSE", "ElectrostaticCharge", 143385)
	self:Log("SPELL_AURA_APPLIED", "ProtectiveFrenzy", 145365)
	self:Log("SPELL_CAST_START", "Sawblade", 143265)
	self:Log("SPELL_CAST_SUCCESS", "SawbladeFallback", 143265)
	self:Log("SPELL_CAST_SUCCESS", "Overcharge", 145774)

	self:Death("ShredderDied", 71591)
	self:Death("Win", 71504)
end

function mod:OnEngage()
	if self:Heroic() then
		self:Berserk(540)
	else
		self:Berserk(600)
	end
	assemblyLineCounter = 1
	shredderCounter = 1
	self:Bar(-8199, 35, shredder, "INV_MISC_ARMORKIT_27") -- Shredder Engage
	self:CDBar(-8195, 9) -- Sawblade
	if self.db.profile.custom_off_mine_marker then
		wipe(markableMobs)
		wipe(marksUsed)
		markTimer = nil
	end
end

--------------------------------------------------------------------------------
-- Event Handlers
--

-- The Assembly Line

function mod:AssemblyLine()
	if (self:Difficulty() == 5 or self:Difficulty() == 6) and assemblyLineHeroic[assemblyLineCounter] then -- Heroic
		self:Message(-8202, "Neutral", "Warning", ("[%d] %s"):format(assemblyLineCounter, assemblyLineHeroic[assemblyLineCounter]), "Inv_crate_03")
		self:CDBar(145774, 48, CL["count"]:format(overchargedHeroic[assemblyLineCounter], assemblyLineCounter))
	elseif (self:Difficulty() == 3 or self:Difficulty() == 4) and assemblyLineNormal[assemblyLineCounter] then -- Normal
		self:Message(-8202, "Neutral", "Warning", ("[%d] %s"):format(assemblyLineCounter, assemblyLineNormal[assemblyLineCounter]), "Inv_crate_03")
	else
		self:Message(-8202, "Neutral", "Warning", L["assembly_line_message"]:format(assemblyLineCounter), "Inv_crate_03")
	end

	assemblyLineCounter = assemblyLineCounter + 1

	if (self:Difficulty() == 5 or self:Difficulty() == 6) and assemblyLineHeroic[assemblyLineCounter] then -- Heroic
		self:Bar(-8202, 40, ("[%d] %s"):format(assemblyLineCounter, assemblyLineHeroic[assemblyLineCounter]), "Inv_crate_03")
	elseif (self:Difficulty() == 3 or self:Difficulty() == 4) and assemblyLineNormal[assemblyLineCounter] then -- Normal
		self:Bar(-8202, 40,  ("[%d] %s"):format(assemblyLineCounter, assemblyLineNormal[assemblyLineCounter]), "Inv_crate_03")
	else
		self:Bar(-8202, 40, ("[%d] %s"):format(assemblyLineCounter, EJ_GetSectionInfo(8202)), "Inv_crate_03")
	end
end

do
	local prev = 0
	function mod:CrawlerMine(args)
		local t = GetTime()
		if t-prev > 5 then
			prev = t
			self:Message(-8212, "Urgent", nil, -8212, 77976) -- mine like icon
		end
	end
end

do
	local prev = 0
	function mod:MagneticCrush(args)
		local t = GetTime()
		if t-prev > 15 then
			prev = t
			self:Message(args.spellId, "Important", "Long")
		end
	end
end

function mod:Superheated(args)
	if self:Me(args.destGUID) then
		self:Message(args.spellId, "Personal", "Info", CL["underyou"]:format(args.spellName))
	end
end

function mod:RAID_BOSS_WHISPER(_, msg, sender)
	if msg:find("Ability_Siege_Engineer_Superheated") then -- laser fixate
		-- might wanna do syncing to get range message working
		self:Message(-8208, "Personal", "Info", L.laser_on_you, 144040)
		self:Flash(-8208)
		self:Say(-8208, L.laser_say, true)
	elseif msg:find("Ability_Siege_Engineer_Detonate") then -- mine fixate
		self:Message(-8212, "Personal", "Info", CL["you"]:format(sender))
		self:Flash(-8212)
	elseif msg:find("143266") then -- Sawblade
		-- this is faster than target scanning, hence why we do it
		sawbladeTarget = UnitGUID("player")
		self:Message(-8195, "Positive", "Info", CL["you"]:format(self:SpellName(143266)))
		self:PrimaryIcon(-8195, "player")
		self:Flash(-8195)
		self:Say(-8195)
	end
end

function mod:ShockwaveMissile()
	self:Message(143639, "Urgent")
end

function mod:ShockwaveMissileOver(args)
	self:Message(args.spellId, "Urgent", nil, CL["over"]:format(args.spellName))
end

function mod:PatternRecognitionApplied(args)
	if self:Me(args.destGUID) then
		self:Bar(-8207, 60)
	end
end

function mod:PatternRecognitionRemoved(args)
	if self:Me(args.destGUID) then
		self:Message(-8207, "Positive", CL["over"]:format(args.spellName))
	end
end

-- Automated Shredders

function mod:ShredderEngage()
	self:Message(-8199, "Attention", self:Tank() and "Long", CL["count"]:format(shredder, shredderCounter), "INV_MISC_ARMORKIT_27")
	shredderCounter = shredderCounter + 1
	overloadCounter = 1
	self:Bar(-8199, 60, CL["count"]:format(shredder, shredderCounter), "INV_MISC_ARMORKIT_27")
	self:Bar(144208, 16) -- Death from Above
	overloadCounter = 1
	self:Bar(145444, 7, CL["count"]:format(self:SpellName(145444), overloadCounter)) -- Overload
end

function mod:Overload(args)
	self:Message(145444, "Attention", self:Healer() and "Long", CL["count"]:format(args.spellName, overloadCounter))
	overloadCounter = overloadCounter + 1
	self:Bar(145444, 11, CL["count"]:format(args.spellName, overloadCounter))
end

function mod:DeathFromAboveApplied(args)
	self:Message(args.spellId, "Attention", "Alert")
end

function mod:DeathFromAbove(args)
	self:Message(args.spellId, "Attention", nil, CL["casting"]:format(args.spellName))
	self:Bar(args.spellId, 41)
end

function mod:ShredderDied()
	self:StopBar(144208) -- Death from Above
	self:StopBar(CL["count"]:format(self:SpellName(145444), overloadCounter)) -- Overload
end

-- Siegecrafter Blackfuse

function mod:ElectrostaticCharge(args)
	self:CDBar(args.spellId, 18)
	self:StackMessage(args.spellId, args.destName, args.amount, "Attention", "Info")
end

function mod:ProtectiveFrenzy(args)
	self:Message(args.spellId, "Attention", "Long")
	local boss
	for i=1, 5 do
		boss = "boss"..i
		if UnitExists(boss) and UnitIsDead(boss) then
			self:Message(-8202, "Positive", nil, CL["other"]:format(L["disabled"], UnitName(boss)), false) -- maybe shorten the unit name?
		end
	end
end

do
	-- rather do this than syncing
	local timer = nil
	local function warnSawblade(self, target, guid)
		sawbladeTarget = guid
		self:PrimaryIcon(-8195, target)
		if not self:Me(guid) then -- we warn for ourself from the BOSS_WHISPER
			if self:Range(target) < 8 then -- 8 is guessed
				self:RangeMessage("saw_blade_near_you", "Personal", "Alarm", mod:SpellName(-8195), 143265)
				--mod:Flash(-8195) -- this is too much for our tactic
			else
				self:TargetMessage(-8195, target, "Positive", "Info")
			end
		end
	end
	function mod:Sawblade(args)
		self:CDBar(-8195, self:Heroic() and 15 or 11)
		sawbladeTarget = nil
		self:GetBossTarget(warnSawblade, 0.4, args.sourceGUID)
	end
	function mod:SawbladeFallback(args)
		 -- don't do anything if we warned for the target already
		if args.destGUID ~= sawbladeTarget then
			warnSawblade(self, args.destName, args.destGUID)
		end
	end
end

function mod:Overcharge(args)
	if not args.destGUID then
		print("WARN", "No destination for overcharge")
		return
	end

	local destId = self:MobId(args.destGUID)

	if destId == 71638 then -- Activated Missile Turret
		self:Message(args.spellId, "Important", "Info", L.overcharged:format(L.missile))
	elseif destId == 71752 then -- Activated Laser Turret
		self:Message(args.spellId, "Important", "Info", L.overcharged:format(L.laser))
	elseif destId == 71795 then -- Activated Crawler Mine Vehicle
		self:Message(args.spellId, "Important", "Info", L.overcharged:format(L.mine))
	elseif destId == 71696 then -- Activated Electromagnet
		self:Message(args.spellId, "Important", "Info", L.overcharged:format(L.magnet))
	else
		print("WARN", "Unknown overcharge target", destId, args.destName)
	end
end
